<template>
	<view class="sel-seat">
		<!-- #ifdef H5 -->
		<view class="back" @click="search_back"><uni-icons type="back" color="#000" size="20"></uni-icons></view>
		<!-- #endif -->
		<!-- top -->
		<view class="seat-head">
			<!-- #ifdef H5 -->
			<text class="sh-title">{{ title }}</text>
			<!-- #endif -->
			<text class="sh-info">{{ info }}</text>
		</view>
		<!-- main -->
		<view class="seat-main">
			<movable-area :style="'height:' + (seatRow * 40 + 350) + 'rpx;'" class="vm-area">
				<movable-view
					:style="'width: 750rpx;height:' + (seatRow * 40 + 350) + 'rpx;'"
					:inertia="true"
					:scale="true"
					:scale-min="0.95"
					:scale-max="2"
					direction="all"
					@change="onMove"
					@scale="onScale"
				>
					<view class="sm-title">
						<text class="text">{{ roomName }}</text>
					</view>
					<view class="sm-screen"><text class="text">银幕中央</text></view>
					<view class="sm-line-center"></view>
					<!-- seat content -->
					<view v-for="(item, index) in seatArray" :key="index" class="sm-cell" :style="'width:' + boxWidth + 'px;height:' + seatSize + 'px'">
						<view
							v-for="(seat, col) in item"
							:key="col"
							class="dp-ib"
							:style="'width:' + seatSize + 'px;height:' + seatSize + 'px'"
							@click="handleChooseSeat(index, col)"
						>
							<image v-if="seat.type === 0" class="sm-icon" src="/static/seat/seat_unselected.png" mode="aspectFit"></image>
							<image v-else-if="seat.type === 1" class="sm-icon" src="/static/seat/seat_selected.png" mode="aspectFit"></image>
							<image v-else-if="seat.type === 2" class="sm-icon" src="/static/seat/seat_bought.png" mode="aspectFit"></image>
						</view>
					</view>
					<view class="sm-line-index" :style="'left: ' + (10 - moveX / scale) + 'px;'">
						<text class="text" :style="'height:' + seatSize + 'px;'" v-for="(m, mindex) in mArr" :key="mindex">{{ m }}</text>
					</view>
				</movable-view>
			</movable-area>
			<view class="fix-tips" v-if="showTis">
				<view class="v-tips">
					<image :style="'width:' + seatSize + 'px;height:' + seatSize + 'px'" src="/static/seat/seat_unselected.png" mode="aspectFit"></image>
					<text class="text">可选</text>
				</view>
				<view class="v-tips">
					<image :style="'width:' + seatSize + 'px;height:' + seatSize + 'px'" src="/static/seat/seat_bought.png" mode="aspectFit"></image>
					<text class="text">不可选</text>
				</view>
				<view class="v-tips">
					<image :style="'width:' + seatSize + 'px;height:' + seatSize + 'px'" src="/static/seat/seat_selected.png" mode="aspectFit"></image>
					<text class="text">选中</text>
				</view>
			</view>
		</view>
		<!-- foot -->
		<view class="seat-foot">
			<view class="sf-recommend" v-if="SelectNum === 0">
				<text class="text">推荐选座</text>
				<view class="sfr-tag" v-for="num in Math.min(max, 6)" :key="num" @click="smartChoose(num + 1)">
					<text class="text">{{ num + 1 }}人</text>
				</view>
			</view>
			<view class="sf-arselect" v-else>
				<text class="text">已选</text>
				<scroll-view scroll-x="true">
					<view class="scr-wrap">
						<view class="sfr-selt" v-for="(optItem, optindex) in optArr" :key="optItem.SeatCode" @click="handleChooseSeat(optItem.rowIndex, optItem.colIndex)">
							<!-- <image src="/static/seat/close.png" class="sfr-close"></image> -->
							<!-- <text class="text">{{ optItem.RowNum + '排' + optItem.ColumnNum + '座' }}</text> -->
							<text class="text">{{ optItem.seatNo }}</text>
							<text class="price">￥{{ optItem.vipPrice / 100|| '' }}</text>
							<view class="sfr-close">X</view>
						</view>
					</view>
				</scroll-view>
			</view>
			<view class="f-btn" :class="{ disabled: SelectNum === 0 }" @click="buySeat">
				<text class="text">{{ SelectNum === 0 ? '请选座位' : `￥ ${aPrice / 100} 确认座位` }}</text>
			</view>
		</view>
	</view>
</template>

<script>
export default {
	name: 'anil-seat',
	props: {
		seatData: {
			type: Array
		},
		max: {
			type: Number,
			default: 4
		},
		title: {
			type: String,
			default: ''
		},
		info: {
			type: String,
			default: ''
		},
		roomName: {
			type: String,
			default: ''
		}
	},
	data() {
		return {
			scaleMin: 1, //h5端为解决1无法缩小问题，设为0.95
			boxWidth: 400, //屏幕宽度px
			space: ' ', //空格
			seatArray: [], //影院座位的二维数组,-1为非座位，0为未购座位，1为已选座位(绿色),2为已购座位(红色),一维行，二维列
			seatRow: 0, //影院座位行数
			seatCol: 0, //影院座位列数
			seatSize: 0, //座位尺寸
			SelectNum: 0, //选择座位数
			moveX: 0, //水平移动偏移量
			scale: 1, //放大倍数
			minRow: 0, //从第几行开始排座位
			minCol: 0, //从第几列开始排座位
			showTis: true, //显示选座提示
			seatList: [], //接口获取的原始位置
			mArr: [], //排数提示
			optArr: [], //选中的座位数组。
			isWXAPP: false
		};
	},
	computed: {
		aPrice() {
			let totalAmount = '';
			if (this.optArr && this.optArr.length) {
				totalAmount = this.optArr.map(item => Number(item.vipPrice)).reduce((prev, curr) => prev + curr);
			}
			return totalAmount;
		},
		rpxNum() {
			return this.boxWidth / 750;
		},
		pxNum() {
			return 750 / this.boxWidth;
		}
	},
	created() {
		//获取宽度
		uni.getSystemInfo({
			success: e => {
				this.boxWidth = e.screenWidth;
				//#ifdef H5
				this.scaleMin = 0.95;
				//#endif
			}
		});
		this.initData();
	},
	methods: {
		// 返回
		search_back() {
			uni.navigateBack();
		},
		initData: function() {
			let arr = this.seatData;
			//假数据说明：SeatCode座位编号，RowNum-行号，ColumnNum-纵号，YCoord-Y坐标，XCoord-X坐标，Status-状态
			let row = 0;
			let col = 0;
			let minCol = parseInt(arr[0].XCoord);
			let minRow = parseInt(arr[0].YCoord);
			for (let i of arr) {
				minRow = parseInt(i.YCoord) < minRow ? parseInt(i.YCoord) : minRow;
				minCol = parseInt(i.XCoord) < minCol ? parseInt(i.XCoord) : minCol;
				row = parseInt(i.YCoord) > row ? parseInt(i.YCoord) : row;
				col = parseInt(i.XCoord) > col ? parseInt(i.XCoord) : col;
			}
			this.seatList = arr;
			this.seatRow = row - minRow + 1;
			this.seatCol = col - minCol + 3;
			this.minRow = minRow;
			this.minCol = minCol - 1;
			this.initSeatArray();
		},
		//初始座位数组
		initSeatArray: function() {
			let seatArray = Array(this.seatRow)
				.fill(0)
				.map(() =>
					Array(this.seatCol).fill({
						type: -1,
						SeatCode: '',
						RowNum: '',
						ColumnNum: ''
					})
				);
			this.seatArray = seatArray;
			this.seatSize = this.boxWidth > 0 ? parseInt(parseInt(this.boxWidth, 10) / (this.seatCol + 1), 10) : parseInt(parseInt(414, 10) / (this.seatCol + 1), 10);
			this.initNonSeatPlace();
		},
		//初始化是座位的地方
		initNonSeatPlace: function() {
			let seat = this.seatList.slice();
			let arr = this.seatArray.slice();
			for (let num in seat) {
				let status = 2; //-1为非座位，0为未购座位，1为已选座位(绿色),2为已购座位(红色)
				if (seat[num].Status === 0) {
					status = 0;
				} else if (seat[num].Status === -1) {
					status = -1;
				}
				arr[parseInt(seat[num].YCoord) - this.minRow][parseInt(seat[num].XCoord) - this.minCol] = {
					type: status,
					SeatCode: seat[num].SeatCode,
					RowNum: seat[num].RowNum,
					ColumnNum: seat[num].ColumnNum,
					Price: seat[num].Price,
					vipPrice: seat[num].vipPrice,
					seatNo: seat[num].seatNo
				};
			}
			this.seatArray = arr.slice();
			let mArr = [];
			let num = 0;
			for (let i in arr) {
				let m = '';
				for (let n of arr[i]) {
					if (n.SeatCode) {
						m = n.RowNum;
					}
				}
				// if (m) {
				// 	mArr.push(m);
				// } else {
				// 	mArr.push('');
				// }
				if (m) {
					num++;
					mArr.push(num);
				} else {
					mArr.push('');
					// mArr[i*1+1]=i*1+1;
				}
			}
			// mArr.pop();
			this.mArr = mArr;
		},
		//放大缩小事件
		onScale: function(e) {
			this.showTis = false;
			// this.moveX=-e.detail.x
			let w = this.boxWidth * 0.5;
			let s = 1 - e.detail.scale;
			this.moveX = w * s;
			this.scale = e.detail.scale;
			if (s > 0 || s === 0) {
				this.showTis = true;
			}
		},
		//移动事件
		onMove: function(e) {
			this.showTis = false;
			this.moveX = e.detail.x;
		},
		//重置座位
		resetSeat: function() {

			this.SelectNum = 0;
			this.optArr = [];
			//将所有已选座位的值变为0
			let oldArray = this.seatArray.slice();
			for (let i = 0; i < this.seatRow; i++) {
				for (let j = 0; j < this.seatCol; j++) {
					if (oldArray[i][j].type === 1) {
						oldArray[i][j].type = 0;
					}
				}
			}
			this.seatArray = oldArray;
		},
		//选定且购买座位
		buySeat: function() {
			if (this.SelectNum === 0) {
				return uni.showToast({
					icon: 'none',
					title: '请至少选择一个座位'
				});
			}
			// let oldArray = [];
			// for (let i = 0; i < this.seatRow; i++) {
			// 	for (let j = 0; j < this.seatCol; j++) {
			// 		if (this.seatArray[i][j].type === 1) {
			// 			oldArray.push(this.seatArray[i][j])
			// 		}
			// 	}
			// }
			// console.log(this.optArr)
			this.$emit('confirm', this.optArr);
		},
		//处理座位选择逻辑
		handleChooseSeat: function(row, col) {
			// console.log('处理座位选择逻辑-row',row);
			// console.log('处理座位选择逻辑-col',col);
			let seatValue = this.seatArray[row][col].type;
			let newArray = this.seatArray;
			// console.log('处理座位选择逻辑-seatValue',seatValue);
			// console.log('处理座位选择逻辑-seatArray',this.seatArray);
			//如果是已购座位，直接返回
			if (seatValue === 2 || seatValue === -1) return;
			//如果是已选座位点击后变未选
			if (seatValue === 1) {
				newArray[row][col].type = 0;
				this.SelectNum--;
				this.getOptArr(newArray[row][col], 0);
			} else if (seatValue === 0) {
				if (this.SelectNum >= this.max) {
					return uni.showToast({
						title: '一次最多选择' + this.max + '张',
						icon: 'none'
					});
				}
				newArray[row][col].rowIndex = row;
				newArray[row][col].colIndex = col;
				newArray[row][col].type = 1;
				this.SelectNum++;
				this.getOptArr(newArray[row][col], 1);
			}
			//必须整体更新二维数组，Vue无法检测到数组某一项更新,必须slice复制一个数组才行
			this.seatArray = newArray.slice();
		},
		//处理已选座位数组
		getOptArr: function(item, type) {
			console.log('处理已选座位数组',item);
			let optArr = this.optArr;
			if (type === 1) {
				optArr.push(item);
			} else if (type === 0) {
				let arr = [];
				optArr.forEach(v => {
					if (v.SeatCode !== item.SeatCode) {
						arr.push(v);
					}
				});
				optArr = arr;
			}
			this.optArr = optArr.slice();
		},
		//推荐选座,参数是推荐座位数目，
		smartChoose: function(num) {
			// console.log('num===', num)
			// 先重置
			this.resetSeat();
			//找到影院座位水平垂直中间位置的后一排
			let rowStart = parseInt((this.seatRow - 1) / 2, 10) + 1;
			//先从中间排往后排搜索
			let backResult = this.searchSeatByDirection(rowStart, this.seatRow - 1, num);
			if (backResult.length > 0) {
				this.chooseSeat(backResult);
				this.SelectNum += num;
				return;
			}
			//再从中间排往前排搜索
			let forwardResult = this.searchSeatByDirection(rowStart - 1, 0, num);
			if (forwardResult.length > 0) {
				this.chooseSeat(forwardResult);
				this.SelectNum += num;
				return;
			}
			//提示用户无合法位置可选
			// #ifdef H5
			alert('无合法位置可选!');
			// #endif
		},

		//搜索函数,参数:fromRow起始行，toRow终止行,num推荐座位数
		searchSeatByDirection: function(fromRow, toRow, num) {
			/*
			 * 推荐座位规则
			 * (1)初始状态从座位行数的一半处的后一排的中间开始向左右分别搜索，取离中间最近的，如果满足条件，
			 *    记录下该结果离座位中轴线的距离，后排搜索完成后取距离最小的那个结果座位最终结果，优先向后排进行搜索，
			 *    后排都没有才往前排搜，前排逻辑同上
			 *
			 * (2)只考虑并排且连续的座位，不能不在一排或者一排中间有分隔
			 *
			 * */

			/*
			 * 保存当前方向搜索结果的数组,元素是对象,result是结果数组，offset代表与中轴线的偏移距离
			 * {
			 *   result:Array([x,y])
			 *   offset:Number
			 * }
			 *
			 */
			let currentDirectionSearchResult = [];

			let largeRow = fromRow > toRow ? fromRow : toRow,
				smallRow = fromRow > toRow ? toRow : fromRow;

			for (let i = smallRow; i <= largeRow; i++) {
				//每一排的搜索,找出该排里中轴线最近的一组座位
				let tempRowResult = [],
					minDistanceToMidLine = Infinity;
				for (let j = 0; j <= this.seatCol - num; j++) {
					//如果有合法位置
					if (this.checkRowSeatContinusAndEmpty(i, j, j + num - 1)) {
						//计算该组位置距离中轴线的距离:该组位置的中间位置到中轴线的距离
						let resultMidPos = parseInt(j + num / 2, 10);
						let distance = Math.abs(parseInt(this.seatCol / 2) - resultMidPos);
						//如果距离较短则更新
						if (distance < minDistanceToMidLine) {
							minDistanceToMidLine = distance;
							//该行的最终结果
							tempRowResult = this.generateRowResult(i, j, j + num - 1);
						}
					}
				}
				//保存该行的最终结果
				currentDirectionSearchResult.push({
					result: tempRowResult,
					offset: minDistanceToMidLine
				});
			}

			//处理后排的搜索结果:找到距离中轴线最短的一个
			//注意这里的逻辑需要区分前后排，对于后排是从前往后，前排则是从后往前找
			let isBackDir = fromRow < toRow;
			let finalReuslt = [],
				minDistanceToMid = Infinity;
			if (isBackDir) {
				//后排情况,从前往后
				currentDirectionSearchResult.forEach(item => {
					if (item.offset < minDistanceToMid) {
						finalReuslt = item.result;
						minDistanceToMid = item.offset;
					}
				});
			} else {
				//前排情况，从后往前找
				currentDirectionSearchResult.reverse().forEach(item => {
					if (item.offset < minDistanceToMid) {
						finalReuslt = item.result;
						minDistanceToMid = item.offset;
					}
				});
			}

			//直接返回结果
			return finalReuslt;
		},

		/*辅助函数，判断每一行座位从i列到j列是否全部空余且连续
		 *
		 */
		checkRowSeatContinusAndEmpty: function(rowNum, startPos, endPos) {
			let isValid = true;
			for (let i = startPos; i <= endPos; i++) {
				if (this.seatArray[rowNum][i].type !== 0) {
					isValid = false;
					break;
				}
			}
			return isValid;
		},
		//辅助函数：返回每一行的某个合理位置的座位数组
		generateRowResult: function(row, startPos, endPos) {
			let result = [];
			for (let i = startPos; i <= endPos; i++) {
				result.push([row, i]);
			}
			return result;
		},
		//辅助函数:智能推荐的选座操作
		chooseSeat: function(result) {
			let opt = this.optArr;
			let oldArray = this.seatArray.slice();
			for (let i = 0; i < result.length; i++) {
				//选定座位
				oldArray[result[i][0]][result[i][1]].rowIndex = result[i][0];
				oldArray[result[i][0]][result[i][1]].colIndex = result[i][1];
				oldArray[result[i][0]][result[i][1]].type = 1;
				this.optArr.push(oldArray[result[i][0]][result[i][1]]);
			}
			this.seatArray = oldArray;
		}
	}
};
</script>

<style lang="scss">
.back {
	position: absolute;
	z-index: 99;
	left: 10rpx;
	top: 10rpx;
	padding: 10rpx 20rpx;
}
.sel-seat {
	position: fixed;
	display: flex;
	flex-direction: column;
	width: 100vw;
	height: 100vh;
	.seat-head {
		background-color: #ffffff;
		display: flex;
		flex-direction: column;
		padding: 20rpx 30rpx;
		position: relative;
		z-index: 5;
		.sh-title {
			font-size: 32rpx;
			font-weight: bold;
			color: #333333;
			text-align: center;
		}
		.sh-info {
			font-size: 24rpx;
			color: #999999;
			margin-top: 10rpx;
			text-align: center;
		}
	}
	.seat-main {
		width: 100%;
		position: relative;
		padding: 10rpx;
		.vm-area {
			width: 750rpx;
		}
		.sm-title {
			background-color: #f9ba37;
			width: 380rpx;
			height: 34rpx;
			transform: perspective(34rpx) rotateX(-10deg);
			margin: 0 auto;
			display: flex;
			align-items: center;
			justify-content: center;
			position: relative;
			z-index: 2;
			.text {
				font-size: 24rpx;
				color: #fff;
			}
		}
		.sm-screen {
			width: 100rpx;
			height: 30rpx;
			border: 1rpx solid #cccccc;
			display: flex;
			align-items: center;
			justify-content: center;
			margin: 48rpx auto 0;
			border-radius: 4rpx;
			position: relative;
			z-index: 1;
			.text {
				font-size: 20rpx;
				color: #999999;
			}
		}
		.sm-line-center {
			height: 610rpx;
			width: 0;
			border: 1rpx dashed #e5e5e5;
			position: fixed;
			left: 50%;
			top: 0;
			display: block;
			z-index: 0;
			transform: translateX(-50%);
		}
		.fix-tips {
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 24rpx;
			position: fixed;
			bottom: 214rpx;
			left: 0;
			width: 100%;
			z-index: 1;
			padding: 20rpx;
			.v-tips {
				display: flex;
				align-items: center;
				color: #999;
				margin: 0 10rpx;
				.text {
					margin-left: 10rpx;
				}
			}
		}
		// seat style
		.sm-cell {
			display: flex;
			margin-top: 20rpx;
			align-items: center;
			justify-content: center;
			position: relative;
			z-index: 2;
			.sm-icon {
				width: 100%;
				height: 100%;
			}
		}
		.sm-line-index {
			position: fixed;
			top: 114rpx;
			left: 20rpx;
			border-radius: 14rpx;
			overflow: hidden;
			background-color: rgba($color: #000000, $alpha: 0.3);
			z-index: 3;
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			padding-bottom: 20rpx;
			width: 30rpx;
			.text {
				font-size: 24rpx;
				color: #ffffff;
				width: 100%;
				text-align: center;
				margin-top: 20rpx;
			}
		}
	}
	.seat-foot {
		margin-top: auto;
		background-color: #ffffff;
		padding: 20rpx 30rpx;
		position: relative;
		z-index: 5;
		.sf-recommend {
			display: flex;
			align-items: center;
			justify-content: center;
			padding-bottom: 20rpx;
			.text {
				font-size: 28rpx;
				color: #666666;
			}
			.sfr-tag {
				width: 110rpx;
				height: 60rpx;
				border-radius: 4rpx;
				border: 1rpx solid #ccc;
				display: flex;
				align-items: center;
				justify-content: center;
				margin-left: 20rpx;
			}
		}
		.sf-arselect {
			@extend .sf-recommend;
			.text {
				font-size: 24rpx;
				color: #666666;
			}
			.price {
				font-size: 20rpx;
				color: red;
			}
			.scr-wrap {
				display: flex;
				white-space: nowrap;
			}
			.sfr-selt {
				min-width: 140rpx;
				height: 60rpx;
				border-radius: 4rpx;
				// border: 1rpx solid #ccc;
				background: #eee;
				display: flex;
				align-items: flex-start;
				justify-content: center;
				flex-direction: column;
				margin-left: 20rpx;
				position: relative;
				margin-left: 20rpx;
				padding: 10rpx 0;
				padding-left: 10rpx;
				.sfr-close {
					position: absolute;
					right: 16rpx;
					top: 10rpx;
					font-size: 20rpx;
					color: #999;
				}
			}
		}
		.f-btn {
			background-color: #f9ba37;
			width: 100%;
			height: 90rpx;
			line-height: 90rpx;
			text-align: center;
			border-radius: 10rpx;
			.text {
				color: #ffffff;
				font-size: 36rpx;
			}
			&.disabled {
				opacity: 0.8;
			}
		}
	}
}
</style>
